package cn.org.wangchangjiu.sqltomongo.core.analyzer.table_option;

import cn.org.wangchangjiu.sqltomongo.core.common.MongoIndex;
import cn.org.wangchangjiu.sqltomongo.core.common.MongoParserResultForCreateTable;
import net.sf.jsqlparser.statement.create.table.ColumnDefinition;
import net.sf.jsqlparser.statement.create.table.CreateTable;
import net.sf.jsqlparser.statement.create.table.Index;
import org.apache.commons.collections4.CollectionUtils;
import org.bson.Document;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class CreateTableColumnAnalyzer {

    public MongoParserResultForCreateTable proceed(CreateTable data) {
        MongoParserResultForCreateTable result = new MongoParserResultForCreateTable();
        result.setCollectionName(data.getTable().getName());
        Document properties = new Document();
        ArrayList<String> required = new ArrayList<>();
        for (ColumnDefinition columnDefinition : data.getColumnDefinitions()) {
            Document property = new Document();
            property.put("bsonType", convertDataType(columnDefinition.getColDataType().getDataType()));
            List<String> list = columnDefinition.getColDataType().getArgumentsStringList();
            if (!CollectionUtils.isEmpty(list)) {
                property.put("maxLength", Integer.valueOf(list.get(0)));
            }
            properties.put(columnDefinition.getColumnName(),property);
            if(isRequired(columnDefinition)){
                required.add(columnDefinition.getColumnName());
            }
        }
        result.setProperties(properties);
        result.setRequired(required);
        List<Index> originIndexes = data.getIndexes();
        if (!CollectionUtils.isEmpty(originIndexes)) {
            ArrayList<MongoIndex> indexes = new ArrayList<>();
            for (Index originIndex : originIndexes) {
                MongoIndex e = new MongoIndex();
                e.setUnique(isUnique(originIndex));
                e.setFields(originIndex.getColumnsNames());
                indexes.add(e);
            }
            result.setIndexes(indexes);
        }

        return result;
    }

    /**
     * 对应sql和mongo的数据类型
     * @param dataType sql的数据类型
     * @return mongo的数据类型
     */
    private String convertDataType(String dataType) {
        if (dataType==null || dataType.equals("")) {
            throw new RuntimeException("sql数据类型为空");
        }
        dataType = dataType.toUpperCase();
        switch (dataType) {
            case "VARCHAR":
            case "TEXT":
            case "CHAR":
            case "TINYTEXT":
            case "MEDIUMTEXT":
            case "LONGTEXT":
                return "string";
            case "INT":
            case "TINYINT":
            case "SMALLINT":
            case "MEDIUMINT":
                return "int";
            case "FLOAT":
            case "DOUBLE":
                return "double";
            case "DECIMAL":
                return "decimal";
            case "DATE":
            case "DATETIME":
            case "TIMESTAMP":
                return "date";
//            case "BLOB":
//            case "TINYBLOB":
//            case "MEDIUMBLOB":
//            case "LONGBLOB":
//            case "BIT":
//                return "Binary";
            case "JSON":
                return "object";
        }
        throw new RuntimeException("不支持的sql数据类型："+dataType);
//        return "Object";
    }

    private boolean isUnique(Index originIndex) {
        String type = originIndex.getType();
        if (type.equals("PRIMARY KEY") || type.equals("UNIQUE")) {
            return true;
        }
        return false;
    }

    private boolean isRequired(ColumnDefinition columnDefinition) {
        List<String> columnSpecs = columnDefinition.getColumnSpecs();
        if (columnSpecs==null) {
            return false;
        }
        for (int i = 0, columnSpecsSize = columnSpecs.size(); i < columnSpecsSize; i++) {
            String columnSpec = columnSpecs.get(i);
            if (Objects.equals(columnSpec.toLowerCase(), "not")
                    && (i+1<columnSpecsSize)
                    && Objects.equals(columnSpecs.get(i + 1).toLowerCase(), "null")) {
                return true;
            }
        }
        return false;
    }
}
